//: net/mindview/util/Countries.java
// "Flyweight" Maps and Lists of sample data.
package net.mindview.util;

import java.util.*;

import static net.mindview.util.Print.*;

public class Countries {
    //随机国家生成器，用来填充容器   key--国家  value--首都
    public static final String[][] DATA = {
        // Africa  国家，首都
        {"ALGERIA", "Algiers"},
        {"ANGOLA", "Luanda"},
        {"BENIN", "Porto-Novo"},
        {"BOTSWANA", "Gaberone"},
        {"BURKINA FASO", "Ouagadougou"},
        {"BURUNDI", "Bujumbura"},
        {"CAMEROON", "Yaounde"},
        {"CAPE VERDE", "Praia"},
        {"CENTRAL AFRICAN REPUBLIC", "Bangui"},
        {"CHAD", "N'djamena"},
        {"COMOROS", "Moroni"},
        {"CONGO", "Brazzaville"},
        {"DJIBOUTI", "Dijibouti"},
        {"EGYPT", "Cairo"},
        {"EQUATORIAL GUINEA", "Malabo"},
        {"ERITREA", "Asmara"},
        {"ETHIOPIA", "Addis Ababa"},
        {"GABON", "Libreville"},
        {"THE GAMBIA", "Banjul"},
        {"GHANA", "Accra"},
        {"GUINEA", "Conakry"},
        {"BISSAU", "Bissau"},
        {"COTE D'IVOIR (IVORY COAST)", "Yamoussoukro"},
        {"KENYA", "Nairobi"},
        {"LESOTHO", "Maseru"},
        {"LIBERIA", "Monrovia"},
        {"LIBYA", "Tripoli"},
        {"MADAGASCAR", "Antananarivo"},
        {"MALAWI", "Lilongwe"},
        {"MALI", "Bamako"},
        {"MAURITANIA", "Nouakchott"},
        {"MAURITIUS", "Port Louis"},
        {"MOROCCO", "Rabat"},
        {"MOZAMBIQUE", "Maputo"},
        {"NAMIBIA", "Windhoek"},
        {"NIGER", "Niamey"},
        {"NIGERIA", "Abuja"},
        {"RWANDA", "Kigali"},
        {"SAO TOME E PRINCIPE", "Sao Tome"},
        {"SENEGAL", "Dakar"},
        {"SEYCHELLES", "Victoria"},
        {"SIERRA LEONE", "Freetown"},
        {"SOMALIA", "Mogadishu"},
        {"SOUTH AFRICA", "Pretoria/Cape Town"},
        {"SUDAN", "Khartoum"},
        {"SWAZILAND", "Mbabane"},
        {"TANZANIA", "Dodoma"},
        {"TOGO", "Lome"},
        {"TUNISIA", "Tunis"},
        {"UGANDA", "Kampala"},
        {"DEMOCRATIC REPUBLIC OF THE CONGO (ZAIRE)", "Kinshasa"},
        {"ZAMBIA", "Lusaka"},
        {"ZIMBABWE", "Harare"},
// Asia
        {"AFGHANISTAN", "Kabul"}, {"BAHRAIN", "Manama"},
        {"BANGLADESH", "Dhaka"}, {"BHUTAN", "Thimphu"},
        {"BRUNEI", "Bandar Seri Begawan"},
        {"CAMBODIA", "Phnom Penh"},
        {"CHINA", "Beijing"}, {"CYPRUS", "Nicosia"},
        {"INDIA", "New Delhi"}, {"INDONESIA", "Jakarta"},
        {"IRAN", "Tehran"}, {"IRAQ", "Baghdad"},
        {"ISRAEL", "Jerusalem"}, {"JAPAN", "Tokyo"},
        {"JORDAN", "Amman"}, {"KUWAIT", "Kuwait City"},
        {"LAOS", "Vientiane"}, {"LEBANON", "Beirut"},
        {"MALAYSIA", "Kuala Lumpur"}, {"THE MALDIVES", "Male"},
        {"MONGOLIA", "Ulan Bator"},
        {"MYANMAR (BURMA)", "Rangoon"},
        {"NEPAL", "Katmandu"}, {"NORTH KOREA", "P'yongyang"},
        {"OMAN", "Muscat"}, {"PAKISTAN", "Islamabad"},
        {"PHILIPPINES", "Manila"}, {"QATAR", "Doha"},
        {"SAUDI ARABIA", "Riyadh"}, {"SINGAPORE", "Singapore"},
        {"SOUTH KOREA", "Seoul"}, {"SRI LANKA", "Colombo"},
        {"SYRIA", "Damascus"},
        {"TAIWAN (REPUBLIC OF CHINA)", "Taipei"},
        {"THAILAND", "Bangkok"}, {"TURKEY", "Ankara"},
        {"UNITED ARAB EMIRATES", "Abu Dhabi"},
        {"VIETNAM", "Hanoi"}, {"YEMEN", "Sana'a"},
// Australia and Oceania
        {"AUSTRALIA", "Canberra"}, {"FIJI", "Suva"},
        {"KIRIBATI", "Bairiki"},
        {"MARSHALL ISLANDS", "Dalap-Uliga-Darrit"},
        {"MICRONESIA", "Palikir"}, {"NAURU", "Yaren"},
        {"NEW ZEALAND", "Wellington"}, {"PALAU", "Koror"},
        {"PAPUA NEW GUINEA", "Port Moresby"},
        {"SOLOMON ISLANDS", "Honaira"}, {"TONGA", "Nuku'alofa"},
        {"TUVALU", "Fongafale"}, {"VANUATU", "< Port-Vila"},
        {"WESTERN SAMOA", "Apia"},
// Eastern Europe and former USSR
        {"ARMENIA", "Yerevan"}, {"AZERBAIJAN", "Baku"},
        {"BELARUS (BYELORUSSIA)", "Minsk"},
        {"BULGARIA", "Sofia"}, {"GEORGIA", "Tbilisi"},
        {"KAZAKSTAN", "Almaty"}, {"KYRGYZSTAN", "Alma-Ata"},
        {"MOLDOVA", "Chisinau"}, {"RUSSIA", "Moscow"},
        {"TAJIKISTAN", "Dushanbe"}, {"TURKMENISTAN", "Ashkabad"},
        {"UKRAINE", "Kyiv"}, {"UZBEKISTAN", "Tashkent"},
// Europe
        {"ALBANIA", "Tirana"}, {"ANDORRA", "Andorra la Vella"},
        {"AUSTRIA", "Vienna"}, {"BELGIUM", "Brussels"},
        {"BOSNIA", "-"}, {"HERZEGOVINA", "Sarajevo"},
        {"CROATIA", "Zagreb"}, {"CZECH REPUBLIC", "Prague"},
        {"DENMARK", "Copenhagen"}, {"ESTONIA", "Tallinn"},
        {"FINLAND", "Helsinki"}, {"FRANCE", "Paris"},
        {"GERMANY", "Berlin"}, {"GREECE", "Athens"},
        {"HUNGARY", "Budapest"}, {"ICELAND", "Reykjavik"},
        {"IRELAND", "Dublin"}, {"ITALY", "Rome"},
        {"LATVIA", "Riga"}, {"LIECHTENSTEIN", "Vaduz"},
        {"LITHUANIA", "Vilnius"}, {"LUXEMBOURG", "Luxembourg"},
        {"MACEDONIA", "Skopje"}, {"MALTA", "Valletta"},
        {"MONACO", "Monaco"}, {"MONTENEGRO", "Podgorica"},
        {"THE NETHERLANDS", "Amsterdam"}, {"NORWAY", "Oslo"},
        {"POLAND", "Warsaw"}, {"PORTUGAL", "Lisbon"},
        {"ROMANIA", "Bucharest"}, {"SAN MARINO", "San Marino"},
        {"SERBIA", "Belgrade"}, {"SLOVAKIA", "Bratislava"},
        {"SLOVENIA", "Ljuijana"}, {"SPAIN", "Madrid"},
        {"SWEDEN", "Stockholm"}, {"SWITZERLAND", "Berne"},
        {"UNITED KINGDOM", "London"}, {"VATICAN CITY", "---"},
// North and Central America
        {"ANTIGUA AND BARBUDA", "Saint John's"},
        {"BAHAMAS", "Nassau"},
        {"BARBADOS", "Bridgetown"}, {"BELIZE", "Belmopan"},
        {"CANADA", "Ottawa"}, {"COSTA RICA", "San Jose"},
        {"CUBA", "Havana"}, {"DOMINICA", "Roseau"},
        {"DOMINICAN REPUBLIC", "Santo Domingo"},
        {"EL SALVADOR", "San Salvador"},
        {"GRENADA", "Saint George's"},
        {"GUATEMALA", "Guatemala City"},
        {"HAITI", "Port-au-Prince"},
        {"HONDURAS", "Tegucigalpa"}, {"JAMAICA", "Kingston"},
        {"MEXICO", "Mexico City"}, {"NICARAGUA", "Managua"},
        {"PANAMA", "Panama City"}, {"ST. KITTS", "-"},
        {"NEVIS", "Basseterre"}, {"ST. LUCIA", "Castries"},
        {"ST. VINCENT AND THE GRENADINES", "Kingstown"},
        {"UNITED STATES OF AMERICA", "Washington, D.C."},
// South America
        {"ARGENTINA", "Buenos Aires"},
        {"BOLIVIA", "Sucre (legal)/La Paz(administrative)"},
        {"BRAZIL", "Brasilia"}, {"CHILE", "Santiago"},
        {"COLOMBIA", "Bogota"}, {"ECUADOR", "Quito"},
        {"GUYANA", "Georgetown"}, {"PARAGUAY", "Asuncion"},
        {"PERU", "Lima"}, {"SURINAME", "Paramaribo"},
        {"TRINIDAD AND TOBAGO", "Port of Spain"},
        {"URUGUAY", "Montevideo"}, {"VENEZUELA", "Caracas"},
    };


    // Use AbstractMap by implementing entrySet()
    private static class FlyweightMap extends AbstractMap<String, String> {

        //静态类嵌套静态类   Map
        private static class Entry implements Map.Entry<String, String> {
            int index;

            Entry(int index) {
                this.index = index;
            }

            public boolean equals(Object o) {
                return DATA[index][0].equals(o);
            }

            public String getKey() {
                return DATA[index][0];
            }

            public String getValue() {
                return DATA[index][1];
            }

            public String setValue(String value) {
                throw new UnsupportedOperationException();
            }

            public int hashCode() {
                return DATA[index][0].hashCode();
            }
        }

        // Use AbstractSet by implementing size() & iterator()  Set
        static class EntrySet extends AbstractSet<Map.Entry<String, String>> {
            private int size;

            EntrySet(int size) {
                if (size < 0) {
                    this.size = 0;
                } else if (size > DATA.length) {// Can't be any bigger than the array:
                    this.size = DATA.length;
                } else {
                    this.size = size;
                }
            }

            public int size() {
                return size;
            }

            private class Iter implements Iterator<Map.Entry<String, String>> {
                // Only one Entry object per Iterator:
                private Entry entry = new Entry(-1);

                public boolean hasNext() {
                    return entry.index < size - 1;
                }

                public Map.Entry<String, String> next() {
                    entry.index++;
                    return entry;
                }

                public void remove() {
                    throw new UnsupportedOperationException();
                }
            }

            public Iterator<Map.Entry<String, String>> iterator() {
                return new Iter();
            }
        }

        private static Set<Map.Entry<String, String>> entries = new EntrySet(DATA.length);

        public Set<Map.Entry<String, String>> entrySet() {
            return entries;
        }
    }

    // Create a partial map of 'size' countries:  部分国家
    static Map<String, String> select(final int size) {
        return new FlyweightMap() {
            public Set<Map.Entry<String, String>> entrySet() {
                return new EntrySet(size);
            }
        };
    }

    static Map<String, String> map = new FlyweightMap();

    public static Map<String, String> capitals() {
        return map; // The entire map
    }

    public static Map<String, String> capitals(int size) {
        return select(size); // A partial map
    }

    static List<String> names = new ArrayList<String>(map.keySet());

    // All the names:
    public static List<String> names() {
        return names;
    }

    // A partial list:
    public static List<String> names(int size) {
        return new ArrayList<String>(select(size).keySet());
    }

    public static void main(String[] args) {
        print(capitals(10));
        print(names(10));
        print(new HashMap<String, String>(capitals(3)));
        print(new LinkedHashMap<String, String>(capitals(3)));
        print(new TreeMap<String, String>(capitals(3)));
        print(new Hashtable<String, String>(capitals(3)));
        print(new HashSet<String>(names(6)));
        print(new LinkedHashSet<String>(names(6)));
        print(new TreeSet<String>(names(6)));
        print(new ArrayList<String>(names(6)));
        print(new LinkedList<String>(names(6)));
        print(capitals().get("BRAZIL"));
        //MyTest
        System.out.println(DATA[1][1]);
//        System.out.println(DATA[1][2]);
        System.out.println(DATA[10][0]+"----"+DATA[10][1]);
    }
} /* Output:
{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo, BOTSWANA=Gaberone, BULGARIA=Sofia, BURKINA FASO=Ouagadougou, BURUNDI=Bujumbura, CAMEROON=Yaounde, CAPE VERDE=Praia, CENTRAL AFRICAN REPUBLIC=Bangui}
[ALGERIA, ANGOLA, BENIN, BOTSWANA, BULGARIA, BURKINA FASO, BURUNDI, CAMEROON, CAPE VERDE, CENTRAL AFRICAN REPUBLIC]
{BENIN=Porto-Novo, ANGOLA=Luanda, ALGERIA=Algiers}
{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo}
{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo}
{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo}
[BULGARIA, BURKINA FASO, BOTSWANA, BENIN, ANGOLA, ALGERIA]
[ALGERIA, ANGOLA, BENIN, BOTSWANA, BULGARIA, BURKINA FASO]
[ALGERIA, ANGOLA, BENIN, BOTSWANA, BULGARIA, BURKINA FASO]
[ALGERIA, ANGOLA, BENIN, BOTSWANA, BULGARIA, BURKINA FASO]
[ALGERIA, ANGOLA, BENIN, BOTSWANA, BULGARIA, BURKINA FASO]
Brasilia
*///:~
